
import {
  ATTR,
  TEXT,
  REPLACE,
  REMOVE
} from './patchesTypes';

let patches = {}, // 保存补丁
    vnIndex = 0; // 保存虚拟节点的节点下标(编号)

// diff运算，比较差异，得到补丁包 walk: 遍历、递归的意思
function domDiff(oldVDom, newVDom) {
  let index = 0; // 私有变量 初始vNodeWalk时使用(根节点、父节点)
  vNodeWalk(oldVDom, newVDom, index);
  return patches;
}

function vNodeWalk(oldNode, newNode, index) { // 遍历虚拟节点获取补丁
  let vnPatch = [];

  if (!newNode) { // 如果新节点不存在 (删除节点操作后)
    // console.log(oldNode, newNode, index);
    vnPatch.push({
      type: REMOVE,
      index
    })
  } else if (typeof oldNode === 'string' && typeof newNode === 'string') { // 判断是否是文本节点
    if(oldNode !== newNode) { // 如果不相同就修改
      vnPatch.push({
        type: TEXT,
        text: newNode
      })
    }
  } else if (oldNode.type === newNode.type) { // 如果标签名相同，就比较属性和子元素
    // 获取比较属性后得到的属性补丁
    const attrPatch = attrsWalk(oldNode.props, newNode.props);
    // console.log(attrPatch);
    if (Object.keys(attrPatch).length > 0) { // 如果不为空
      vnPatch.push({
        type: ATTR,
        attrs: attrPatch
      })
    }
    // 遍历子元素
    // if (newNode.children)
    childrenWalk(oldNode.children, newNode.children);
  } else { // 如果是替换(或之前不存在)
    // console.log(oldNode, newNode, index);
    vnPatch.push({
      type: REPLACE,
      newNode
    })
  }

  if (vnPatch.length > 0) { // 如果遍历的这个节点存在补丁就保存
    patches[index] = vnPatch;
  }
}

function attrsWalk(oldAttrs, newAttrs) { // 比较属性
  let attrPatch = {};

  for (let key in oldAttrs) {
    if (oldAttrs[key] !== newAttrs[key]) { // 修改属性
      attrPatch[key] = newAttrs[key];
    }
  }

  for(let key in newAttrs) {
    if (!oldAttrs.hasOwnProperty(key)) { // 添加属性
      attrPatch[key] = newAttrs[key];
    }
  }

  return attrPatch;
}

function childrenWalk(oldChildren, newChildren = []) { // 递归遍历子元素
  oldChildren.map((c, idx) => {
    // ++ vnIndex: 保证是深度遍历，逐层向下遍历子元素
    vNodeWalk(c, newChildren[idx], ++ vnIndex);
  })
}

export default domDiff;

// const patches = { // 补丁包结构
//   0: [
//     {
//       type: 'ATTR',
//       attrs: {
//         class: '属性'
//       }
//     }
//   ],
//   1: [
//     {
//       type: 'TEXT',
//       text: 'xxxxxx'
//     }
//   ],
//   3: [
//     {
//       type: 'REMOVE',
//       index: 3
//     }
//   ],
//   6: [
//     {
//       type: 'REPLACE',
//       newNode: newNode
//     }
//   ]
// }